package com.bear.fastrepair.service

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.*
import android.text.TextUtils
import android.util.Log
import com.bear.fastrepair.MainActivity
import com.bear.fastrepair.entity.EmployeeAddressInfo
import com.bear.fastrepair.http.api.EmployeeService
import com.bear.fastrepair.http.client.RetrofitManager
import com.bear.fastrepair.utils.*
import com.blankj.utilcode.util.LogUtils
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener

class NotificationService : Service() {

    private lateinit var serviceHandler: Handler
    private lateinit var serviceHandlerThread: HandlerThread
    private val binder = NotificationBinder()
    private var employeeId = ""
    private var webSocketConnected = false
    private var notificationCount = 1100
    var notifyListener: ((String?) -> Unit)? = null
    private var webSocket: WebSocket? = null

    override fun onBind(intent: Intent): IBinder {
        return binder
    }

    @SuppressLint("UnspecifiedImmutableFlag")
    override fun onCreate() {
        super.onCreate()
        serviceHandlerThread = HandlerThread("service_handler_thread").apply { start() }
        serviceHandler = Handler(serviceHandlerThread.looper)
        postLocationInfo()
        val intent = Intent(this, MainActivity::class.java)
        startForeground(
            NotificationHelper.notificationId,
            NotificationHelper.createNotification(
                this,
                "小熊快修祝您生活愉快",
                PendingIntent.getActivity(this, 1001, intent, 0)
            )
        )
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        stopForeground(true)
        serviceHandlerThread.quitSafely()
        serviceHandler.removeCallbacksAndMessages(null)
        webSocket?.cancel()
    }

    inner class NotificationBinder : Binder() {
        fun startWebSocket(employeeId: String) {
            if (TextUtils.isEmpty(employeeId) || webSocketConnected) return
            this@NotificationService.employeeId = employeeId
            if (webSocket == null) webSocket =
                WebSocketHelper.createWebSocketConnection(employeeId, webSocketListener)
        }

        fun getService() = this@NotificationService
    }

    private val webSocketListener = object : WebSocketListener() {
        override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
            super.onClosed(webSocket, code, reason)
            webSocketConnected = false
            LogUtils.i("============= onClosed")
            serviceHandler.postDelayed({
                Log.w(
                    this@NotificationService.javaClass.simpleName,
                    "onClosed: web socket connect retry"
                )
                binder.startWebSocket(employeeId)
            }, 20000)
        }

        override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
            super.onClosing(webSocket, code, reason)
            webSocketConnected = false
            LogUtils.i("============= onClosing")
        }

        override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
            super.onFailure(webSocket, t, response)
            LogUtils.i("============= onFailure")
            webSocketConnected = false
            this@NotificationService.webSocket?.cancel()
            this@NotificationService.webSocket = null
            serviceHandler.postDelayed({
                Log.w(
                    this@NotificationService.javaClass.simpleName,
                    "onFailure: web socket connect retry"
                )
                binder.startWebSocket(employeeId)
            }, 20000)
            serviceHandler.removeCallbacks(heartBeatTask)
        }

        @SuppressLint("UnspecifiedImmutableFlag")
        override fun onMessage(webSocket: WebSocket, text: String) {
            super.onMessage(webSocket, text)
            LogUtils.i("=========== onMessage")
            val intent = Intent(this@NotificationService, MainActivity::class.java).apply {
                action = NEW_ORDER_NOTIFY_ACTION
                flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
                val data = Bundle()
                data.putString(NEW_ORDER_NOTIFY, text)
                putExtra(NEW_ORDER_NOTIFY, data)
            }
            val pendingIntent = PendingIntent.getActivity(
                this@NotificationService,
                1002,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )
            NotificationHelper.showNotification(
                this@NotificationService,
                "有新的订单派发给你啦，点击查看详情",
                notificationCount++,
                pendingIntent
            )
            notifyListener?.invoke(text)
        }

        override fun onOpen(webSocket: WebSocket, response: Response) {
            super.onOpen(webSocket, response)
            if (webSocketConnected) {
                LogUtils.i("webSocket has been opened")
                return
            }
            LogUtils.i("============= onOpen")
            serviceHandler.postDelayed(heartBeatTask, 10 * 1000)
            webSocketConnected = true
        }
    }

    private val heartBeatTask = object : Runnable {
        override fun run() {
            if (webSocketConnected) {
                Log.i(this@NotificationService.javaClass.simpleName, "send heart beat")
                webSocket?.send("heart beat")
            }
            serviceHandler.postDelayed(this, 1 * 1000L * 50)
        }
    }

    private val delayUpdateLocationTask = object : Runnable {
        override fun run() {
            val token = SharedPreferencesHelper.getStringNormal(ACCOUNT_TOKEN_KEY) ?: ""
            val workStatus = SharedPreferencesHelper.getIntNormal(WORK_STATUS_KEY)
            Log.i(
                "delayUpdateLocationTask",
                "employeeId $employeeId token is null? ${TextUtils.isEmpty(token)} workStatus: $workStatus"
            )
            if (!TextUtils.isEmpty(employeeId) && !TextUtils.isEmpty(token) && workStatus == 1) {
                LocationHelper.getLocationInfoNormal(this@NotificationService) {
                    it ?: run {
                        LocationHelper.getLocationLocal(this@NotificationService) { lat, long ->
                            RetrofitManager.getServiceSetToken(
                                URL_MOBILE,
                                EmployeeService::class.java,
                                token
                            ).refreshEmployeeAddressAuto(EmployeeAddressInfo(null, "$lat", "$long"))
                                .execute()
                        }
                        return@getLocationInfoNormal
                    }
                    val result = RetrofitManager.getServiceSetToken(
                        URL_MOBILE,
                        EmployeeService::class.java,
                        token
                    )
                        .refreshEmployeeAddressAuto(
                            EmployeeAddressInfo(
                                it.address,
                                "${it.latitude}", "${it.longitude}"
                            )
                        ).execute()
//                    Log.i(
//                        "delayUpdateLocationTask",
//                        "postLocationInfo: location is ${it.address} result: ${result.body()}"
//                    )
                }
            }
            serviceHandler.postDelayed(this, 2 * 60 * 1000L)
        }
    }

    private fun postLocationInfo() {
        serviceHandler.post(delayUpdateLocationTask)
    }
}